home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.3 (Developer)…68k, x86, SPARC, PA-RISC] / NeXTSTEP 3.3 Dev Intel.iso / NextDeveloper / Examples / DriverKit / SoundBlaster8 / SoundBlaster8_reloc.tproj / SoundBlaster8Inline.h < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-07  |  17.3 KB  |  785 lines

  1. /*
  2.  * Copyright (c) 1994 NeXT Computer, Inc.  All rights reserved. 
  3.  *
  4.  * HISTORY
  5.  * 4-Mar-94    Rakesh Dubey at NeXT
  6.  *      Created. 
  7.  */
  8.  
  9. /*
  10.  * Base address. 
  11.  */
  12. static unsigned int sbBaseRegisterAddress = 0;
  13.  
  14. /*
  15.  * Register addresses. The base register addressess are determined at
  16.  * run-time. 
  17.  */
  18.  
  19. static unsigned int sbResetReg = 0;
  20. static unsigned int sbReadDataReg = 0;
  21. static unsigned int sbWriteDataOrCommandReg = 0;
  22.  
  23. static unsigned int sbWriteBufferStatusReg = 0;
  24. static unsigned int sbDataAvailableStatusReg = 0;
  25.  
  26. static __inline__
  27. void
  28. assignDSPRegAddresses(void)
  29. {
  30.     sbResetReg = 
  31.         (sbBaseRegisterAddress + SB_DSP_RESET_OFFSET);
  32.     sbReadDataReg = 
  33.         (sbBaseRegisterAddress + SB_DSP_READ_DATA_OFFSET);
  34.     sbWriteDataOrCommandReg = 
  35.         (sbBaseRegisterAddress + SB_DSP_WRITE_DATA_OR_COMMAND_OFFSET);
  36.         
  37.     sbWriteBufferStatusReg = 
  38.         (sbBaseRegisterAddress + SB_DSP_WRITE_BUFFER_STATUS_OFFSET);
  39.     sbDataAvailableStatusReg = 
  40.         (sbBaseRegisterAddress + SB_DSP_DATA_AVAILABLE_STATUS_OFFSET);
  41. }
  42.  
  43.  
  44. /*
  45.  * Print what is being written. 
  46.  */
  47. static __inline__
  48. void
  49. outbV(unsigned int address, unsigned int data)
  50. {
  51. #ifdef DEBUG
  52.     IOLog("SoundBlaster8: Writing %x at address %x\n", data, address);
  53. #endif DEBUG
  54.     outb(address, data);
  55. }
  56.  
  57. static unsigned int sbMixerAddressReg = 0;
  58. static unsigned int sbMixerDataReg = 0;
  59.  
  60. static __inline__
  61. void
  62. assignMixerRegAddresses(void)
  63. {
  64.     sbMixerAddressReg = 
  65.         (sbBaseRegisterAddress + SB_MIXER_ADDRESS_OFFSET);
  66.     sbMixerDataReg = 
  67.         (sbBaseRegisterAddress + SB_MIXER_DATA_OFFSET);
  68. }
  69.  
  70. /*
  71.  * Shadow registers for volume. Add more to this list when necessary. 
  72.  */
  73.  
  74. static sbStereoMixerRegister_t volMaster =     {0};
  75. static sbStereoMixerRegister_t volFM =         {0};
  76. static sbStereoMixerRegister_t volLine =     {0};
  77. static sbStereoMixerRegister_t volVoc =     {0};
  78.  
  79. static sbMonoMixerRegister_t volMic =         {0};
  80. static sbMonoMixerRegister_t volCD =         {0};
  81.  
  82. static sbRecordingMode_t sbRecord =         {0};
  83. static sbPlaybackMode_t sbPlayback =         {0};
  84.  
  85.  
  86. #define MAX_WAIT_FOR_DATA_AVAILABLE         2000
  87. #define SB_WAIT_DELAY                       10
  88. #define SB_RESET_DELAY                      100
  89.  
  90. static  __inline__
  91. BOOL
  92. dspReadWait()
  93. {
  94.     int     i;
  95.     unsigned int val;
  96.  
  97.     for (i = 0; i < MAX_WAIT_FOR_DATA_AVAILABLE; i++) {
  98.     IODelay(SB_WAIT_DELAY);
  99.     val = inb(sbDataAvailableStatusReg);
  100.     if (val & 0x080)   /* MSB == 1 before reading */
  101.         return YES;
  102.     }
  103.  
  104.     /* Reset DSP, hopefully we will recover. */
  105.     outbV(sbResetReg, 0x01);
  106.     IODelay(SB_ADDRESS_WRITE_DELAY);
  107.     outbV(sbResetReg, 0x00);
  108.     IODelay(SB_ADDRESS_WRITE_DELAY);
  109.     IODelay(SB_RESET_DELAY);
  110.  
  111. #ifdef DEBUG
  112.     IOLog("SoundBlaster8: DSP not ready for reading!\n");
  113. #endif DEBUG
  114.  
  115.     return NO;
  116. }
  117.  
  118. static __inline__
  119. BOOL 
  120. dspWriteWait()
  121. {
  122.     int     i;
  123.     unsigned int val;
  124.  
  125.     for (i = 0; i < MAX_WAIT_FOR_DATA_AVAILABLE; i++) {
  126.     IODelay(SB_WAIT_DELAY);
  127.     val = inb(sbWriteBufferStatusReg);
  128.     if (!(val & 0x080))    /* MSB == 0 before writing */
  129.         return YES;
  130.     }
  131.  
  132.     /* Reset DSP */
  133.     outbV(sbResetReg, 0x01);
  134.     IODelay(SB_ADDRESS_WRITE_DELAY);
  135.     outbV(sbResetReg, 0x00);
  136.     IODelay(SB_ADDRESS_WRITE_DELAY);
  137.     IODelay(SB_RESET_DELAY);
  138.  
  139. #ifdef DEBUG
  140.     IOLog("SoundBlaster8: DSP not ready for writing!\n");
  141. #endif DEBUG
  142.  
  143.     return NO;
  144. }
  145.  
  146. /*
  147.  * Send some data or command to SoundBlaster8 DSP. 
  148.  */
  149. static
  150. BOOL
  151. writeToDSP(unsigned int dataOrCommand)
  152. {
  153.     outbV(sbWriteDataOrCommandReg, dataOrCommand);
  154.     IODelay(SB_DATA_WRITE_DELAY);
  155.  
  156. #ifdef DEBUG
  157.     //IOLog("SoundBlaster8: Wrote DSP command %x\n", dataOrCommand);
  158. #endif DEBUG
  159.  
  160.     return YES;
  161. }
  162.  
  163. /*
  164.  * Read from the SoundBlaster DSP. 
  165.  */
  166. static
  167. unsigned int
  168. readFromDSP(void)
  169. {
  170.     unsigned int val;
  171.     
  172.     val = inb(sbReadDataReg);
  173.     IODelay(SB_DATA_READ_DELAY);
  174.  
  175. #ifdef DEBUG
  176.     IOLog("SoundBlaster8: read from DSP %x\n", val);
  177. #endif DEBUG
  178.  
  179.     return val;
  180. }
  181.     
  182. /*
  183.  * Function to read from the Mixer registers. 
  184.  */
  185. static __inline__
  186. unsigned int
  187. inbIXMixer(unsigned int address)
  188. {
  189.     unsigned int val = 0xff;
  190.         
  191.     outbV(sbMixerAddressReg, address);
  192.     IODelay(SB_ADDRESS_WRITE_DELAY);
  193.     val = inb(sbMixerDataReg);
  194.     
  195. #ifdef DEBUG
  196.     IOLog("SoundBlaster8: Mixer address %x. Read %x\n", address, val);
  197. #endif DEBUG
  198.     return val;
  199. }
  200.  
  201. /*
  202.  * Function to write to the Mixer registers. 
  203.  */
  204. static  __inline__
  205. void
  206. outbIXMixer(unsigned int address, unsigned int val)
  207. {
  208.     outbV(sbMixerAddressReg, address);
  209.     IODelay(SB_ADDRESS_WRITE_DELAY);
  210.     outbV(sbMixerDataReg, val);
  211.     IODelay(SB_DATA_WRITE_DELAY);
  212.  
  213. #ifdef DEBUG
  214.     IOLog("SoundBlaster8: Mixer address %x. Wrote %x\n", address, val);
  215. #endif DEBUG
  216. }
  217.  
  218. /*
  219.  * Initialize DSP registers. There aren't any.
  220.  */
  221.  
  222. static __inline__
  223. void
  224. initDSPRegisters(void)
  225. {
  226. }
  227.  
  228. /*
  229.  * Initialize the registers on the Mixer. 
  230.  */
  231.  
  232. static __inline__
  233. void
  234. initMixerRegisters(void)
  235. {
  236.     if (sbCardType.mixerPresent == NO)
  237.         return;
  238.  
  239. #ifdef DEBUG
  240.     IOLog("SoundBlaster8: Initializing mixer registers.\n");
  241. #endif DEBUG
  242.  
  243.     /*
  244.      * First set the volume controlling registers to their default values. 
  245.      */
  246.     volMaster.reg.left = 10;
  247.     volMaster.reg.right = 10;
  248.     outbIXMixer(MC_MASTER_VOLUME, volMaster.data);
  249.     
  250.     volFM.reg.left = 0;
  251.     volFM.reg.right = 0;
  252.     outbIXMixer(MC_FM_VOLUME, volFM.data);
  253.     
  254.     volCD = 0;
  255.     outbIXMixer(MC_CD_VOLUME, volCD);
  256.     
  257.     volLine.reg.left = 0;
  258.     volLine.reg.right = 0;
  259.     outbIXMixer(MC_LINE_VOLUME, volLine.data);
  260.     
  261.     volVoc.reg.left = 10;
  262.     volVoc.reg.right = 10;
  263.     outbIXMixer(MC_VOC_VOLUME, volVoc.data);
  264.     
  265.     /* Microphone can go only upto 7. */
  266.     volMic = 6;
  267.     outbIXMixer(MC_MICROPHONE_VOLUME, volMic);
  268.     
  269.     /* 
  270.      * Now set the record and playback mode registers.
  271.      */
  272.     sbRecord.data = 0;
  273.     sbRecord.reg.source = SB_RECORD_SOURCE_MIC;
  274.     sbRecord.reg.inputFilter = SB_RECORD_ANFI_OFF;
  275.     sbRecord.reg.highFreq = SB_RECORD_FREQ_HIGH;
  276.     outbIXMixer(MC_RECORD_CONTROL, sbRecord.data);
  277.     
  278.     sbPlayback.data = 0;
  279.     sbPlayback.reg.outputFilter = SB_PLAYBACK_DNFI_OFF;
  280.     sbPlayback.reg.stereo = SB_PLAYBACK_STEREO;
  281.     outbIXMixer(MC_PLAYBACK_CONTROL, sbPlayback.data);
  282. }
  283.  
  284. /*
  285.  * Input can be either microphone level or line level. We don't support other
  286.  * inputs. 
  287.  */
  288.  
  289. static __inline__
  290. void
  291. setInputLevel(unsigned int level)
  292. {
  293.     if (sbCardType.mixerPresent == NO)
  294.         return;
  295.         
  296.     if (level == LINE_LEVEL_INPUT)      {
  297.         sbRecord.reg.source = SB_RECORD_SOURCE_LINE;
  298.     } else {
  299.         sbRecord.reg.source = SB_RECORD_SOURCE_MIC;
  300.     }
  301.     
  302.     outbIXMixer(MC_RECORD_CONTROL, sbRecord.data);
  303. }
  304.  
  305. /*
  306.  * Output level cannot be changed. 
  307.  */
  308.  
  309. static __inline__
  310. void
  311. setOutputLevel(unsigned int channel, unsigned int level)
  312. {
  313. #ifdef DEBUG
  314.     IOLog("SoundBlaster8: Audio output level is fixed.\n");
  315. #endif DEBUG
  316. }
  317.  
  318. /*
  319.  * Initialize the hardware registers. 
  320.  */
  321. static __inline__
  322. void 
  323. initRegisters(void)
  324. {
  325.     initDSPRegisters();
  326.     initMixerRegisters();
  327. }
  328.  
  329.  
  330. /*
  331.  * These two routines are used to avoid clicks. 
  332.  */
  333.  
  334. static __inline__
  335. void 
  336. muteOutput(void)
  337. {
  338.     sbStereoMixerRegister_t volMaster = {0};
  339.     
  340.     if (sbCardType.mixerPresent == NO)
  341.         return;
  342.                 
  343.     volMaster.reg.left = 0;
  344.     volMaster.reg.right = 0;
  345.     
  346.     outbIXMixer(MC_MASTER_VOLUME, volMaster.data);
  347. }
  348.  
  349. /*
  350.  * This takes it back to the old values. So it is not exactly unmute.
  351.  */
  352. static __inline__
  353. void 
  354. unMuteOutput(void)
  355. {
  356.     if (sbCardType.mixerPresent == NO)
  357.         return;
  358.         
  359.     outbIXMixer(MC_MASTER_VOLUME, volMaster.data);
  360. }
  361.  
  362. /*
  363.  * This routine does a quick reset of the card. This is needed because
  364.  * apparently the SoundBlaster8 cards need to be reset if you go from the
  365.  * high speed to the low speed mode (wonderful world of hardware). 
  366.  */
  367.  
  368. static __inline__
  369. void
  370. resetDSPQuick(void)
  371. {
  372.     outbV(sbResetReg, 0x01);
  373.     IODelay(SB_ADDRESS_WRITE_DELAY);
  374.     outbV(sbResetReg, 0x00);
  375.     IODelay(SB_ADDRESS_WRITE_DELAY);
  376.     
  377.     /* It takes about 100us to reset */
  378.     dspReadWait();
  379.     if (readFromDSP() != 0xaa)    {
  380.         IOLog("SoundBlaster8: Can not reset DSP.\n");
  381.     }
  382. }
  383.  
  384.  
  385. #define SB_DELAY                               100
  386. #define MAX_RESET_WAIT                      1000
  387.  
  388. /*
  389.  * Reset the SoundBlaster card. This routine also detects if the card is
  390.  * present and the type of card. 
  391.  */
  392. static __inline__
  393. void
  394. resetDSP(void)
  395. {
  396.     unsigned int val;
  397.  
  398.     /*
  399.      * Assume no sound card in the system. 
  400.      */
  401.     sbCardType.version = SB_NONE;
  402.     sbCardType.name = "";
  403.     sbCardType.majorVersion = 0;
  404.     sbCardType.minorVersion = 0;
  405.     sbCardType.mixerPresent = NO;
  406.     
  407.     outbV(sbResetReg, 0x01);
  408.     IODelay(SB_ADDRESS_WRITE_DELAY);
  409.     outbV(sbResetReg, 0x00);
  410.     IODelay(SB_ADDRESS_WRITE_DELAY);
  411.     
  412.     /* Now we can read the data. */
  413.     dspReadWait();
  414.     val = readFromDSP();
  415.     if (val == 0xaa)    {
  416. #ifdef DEBUG
  417.         IOLog("SoundBlaster8: DSP detected.\n");
  418. #endif DEBUG
  419.         IOSleep(1);
  420.     } else {
  421. #ifdef DEBUG
  422.         IOLog("SoundBlaster8: Read ID %x is wrong.\n", val);
  423.         IOLog("SoundBlaster8: SoundBlaster not detected at address 0x%0x.\n", 
  424.                 sbBaseRegisterAddress);
  425. #endif DEBUG
  426.         return;
  427.     }
  428.  
  429.     /*
  430.      * We have a SoundBlaster card. We will upgrade it to a pro if we detect
  431.      * a mixer as well. 
  432.      */
  433.     sbCardType.version = SB_CLASSIC;
  434.  
  435.     /*
  436.      * Another confirmatory test here. This is not documented in the SB SDK
  437.      * so it might fail on some compatible cards. Maybe we should just print
  438.      * a warning message if this test fails. 
  439.      */
  440.     dspWriteWait();
  441.     writeToDSP(DC_INVERT_BYTE);
  442.     
  443.     dspWriteWait();
  444.     writeToDSP(0x43);   /* Send some test pattern. */
  445.     
  446.     dspReadWait();
  447.     val = readFromDSP();
  448.     
  449.     if (val == 0xbc)    {
  450. #ifdef DEBUG
  451.         IOLog("SoundBlaster8: Invert test passed.\n");
  452. #endif DEBUG
  453.     } else      {
  454. #ifdef DEBUG
  455.         IOLog("SoundBlaster8: Invert test failed!!\n");
  456.         IOLog("SoundBlaster8: SoundBlaster not detected at address 0x%0x.\n", 
  457.                 sbBaseRegisterAddress);
  458. #endif DEBUG
  459.     }
  460.  
  461.     /*
  462.      * Reset the DSP here because sometimes you may get crazy values as
  463.      * version. So just to be on the safe side.. 
  464.      */
  465.     resetDSPQuick();
  466.     
  467.     /*
  468.      * Now we know that a SoundBlaster or compatible card exists. We need to
  469.      * find the version number to decide the type of card.
  470.      */
  471.     dspWriteWait();
  472.     writeToDSP(DC_GET_VERSION);
  473.  
  474.     dspReadWait();
  475.     sbCardType.majorVersion = readFromDSP() & 0x0f;
  476.     sbCardType.minorVersion = readFromDSP() & 0x0f;
  477.     
  478. #ifdef DEBUG
  479.     //IOLog("SoundBlaster8: Major 0x%x Minor 0x%x\n", sbCardType.majorVersion, sbCardType.minorVersion);
  480. #endif DEBUG
  481.  
  482.     /*
  483.      * Upgrade the card to SB_20 or SB_16 depending upon what the version
  484.      * number reads. 
  485.      */
  486.     if (sbCardType.majorVersion >= 2)
  487.         sbCardType.version = SB_20;
  488.  
  489.     if (sbCardType.majorVersion >= 4)
  490.         sbCardType.version = SB_16;
  491. }
  492.  
  493.  
  494.  
  495. static __inline__
  496. void
  497. resetMixer(void)
  498. {
  499.     unsigned int val1, val2;
  500.     
  501.     /*
  502.      * Reset the mixer by sending zero to both address and data ports.
  503.      */
  504.      outbIXMixer(0x0, 0x0);
  505.  
  506.     /*
  507.      * Now try to write and then read from one of the mixer registers. 
  508.      */
  509.      outbIXMixer(MC_MASTER_VOLUME, 0x15);
  510.      outbIXMixer(MC_MICROPHONE_VOLUME, 0x13);
  511.      
  512.      val1 = inbIXMixer(MC_MASTER_VOLUME);
  513.      val2 = inbIXMixer(MC_MICROPHONE_VOLUME);
  514.  
  515.     if ((val1 == 0x15) && (val2 == 0x13)) {
  516.     sbCardType.mixerPresent = YES;
  517.     } else {
  518.     sbCardType.mixerPresent = NO;
  519.     }
  520.                 
  521.     /*
  522.      * Try once more, so that we are really sure. 
  523.      */
  524.      outbIXMixer(MC_LINE_VOLUME, 0x17);
  525.      outbIXMixer(MC_FM_VOLUME, 0x19);
  526.  
  527.      val1 = inbIXMixer(MC_LINE_VOLUME);
  528.      val2 = inbIXMixer(MC_FM_VOLUME);
  529.  
  530.     if ((val1 == 0x17) && (val2 == 0x19)) {
  531.     sbCardType.mixerPresent = YES;
  532.     } else {
  533.     sbCardType.mixerPresent = NO;
  534.     }
  535.  
  536.     /*
  537.      * We have a pro card if we found the mixer. 
  538.      */
  539.     if (sbCardType.mixerPresent == YES) {
  540.         sbCardType.version = SB_PRO;
  541.         outbIXMixer(0x0, 0x0);          /* reset the mixer to a good state */
  542.     }
  543.      
  544. #ifdef DEBUG
  545.      if (sbCardType.mixerPresent == YES)
  546.         IOLog("SoundBlaster8: Mixer detected.\n");
  547.      else
  548.         IOLog("SoundBlaster8: Mixer not detected.\n");
  549. #endif DEBUG
  550. }
  551.  
  552.  
  553. /*
  554.  * Reset all hardware and bring us back to the default state. 
  555.  */
  556. static __inline__
  557. void 
  558. resetHardware(void)
  559. {
  560.     resetDSP();
  561.     resetMixer();
  562.     initRegisters();
  563. }
  564.  
  565. /*
  566.  * There seems to be no way to change input gain. 
  567.  */
  568. static  __inline__
  569. void 
  570. setInputGain(unsigned int channel, unsigned int gain)
  571. {
  572.     if (sbCardType.mixerPresent == NO)
  573.         return;
  574.         
  575.     volMic = gain;
  576.     outbIXMixer(MC_MICROPHONE_VOLUME, volMic);
  577.     
  578. #ifdef DEBUG
  579.     IOLog("SoundBlaster8: set input gain %d\n", gain);
  580. #endif DEBUG
  581. }
  582.  
  583. static  __inline__
  584. void
  585. setOutputAttenuation(unsigned int channel, unsigned int attenuation)
  586. {
  587.     if (sbCardType.mixerPresent == NO)
  588.         return;
  589.         
  590.     if (channel == LEFT_CHANNEL) {
  591.         volMaster.reg.left = attenuation;
  592.         outbIXMixer(MC_MASTER_VOLUME, volMaster.data);
  593.  
  594.     } else {
  595.         volMaster.reg.right = attenuation;
  596.         outbIXMixer(MC_MASTER_VOLUME, volMaster.data);
  597.     }
  598. #ifdef DEBUG
  599.     IOLog("SoundBlaster8: set output attenuation %d\n", attenuation);
  600. #endif DEBUG
  601. }
  602.  
  603. /*
  604.  * This will not work for SB16 running in SBPro compatibility mode. The mixer
  605.  * registers need to be written to mute output. 
  606.  */
  607.  
  608. static __inline__
  609. void
  610. enableAudioOutput(BOOL enable)
  611. {
  612.     dspWriteWait();
  613.     if (enable) {
  614.         writeToDSP(DC_TURN_ON_SPEAKER);
  615.     } else {
  616.         writeToDSP(DC_TURN_OFF_SPEAKER);
  617.     }
  618. }
  619.  
  620. static  __inline__
  621. void    setSampleBufferCounter(unsigned int count)
  622. {
  623.     if (!lowSpeedDMA)    {
  624.     dspWriteWait();
  625.         writeToDSP(DC_SET_BLOCK_SIZE);
  626.     } 
  627.     
  628.     count -= 1;
  629.     dspWriteWait();
  630.     writeToDSP(count & 0x0ff);
  631.     dspWriteWait();
  632.     writeToDSP((count >> 8) & 0x0ff);
  633. #ifdef DEBUG
  634.     //IOLog("SoundBlaster8: buffer counter set to %x\n", count);
  635. #endif DEBUG
  636. }
  637.  
  638. /*
  639.  * Start DMA. Command patterns are different depending upon whether we are
  640.  * doing low speed or high speed transfers. 
  641.  */
  642.      
  643. static __inline__
  644. void startDMA(unsigned int direction)
  645. {       
  646.     dspWriteWait();
  647.     if (lowSpeedDMA)    {
  648.         if (direction == DMA_DIRECTION_IN) 
  649.             writeToDSP(DC_START_LS_DMA_ADC_8);
  650.         else
  651.             writeToDSP(DC_START_LS_DMA_DAC_8);
  652.     } else {
  653.         if (direction == DMA_DIRECTION_IN) 
  654.             writeToDSP(DC_START_HS_DMA_ADC_8);
  655.         else
  656.             writeToDSP(DC_START_HS_DMA_DAC_8);
  657.     }
  658. }
  659.  
  660. /* No can do */
  661. static __inline__
  662. void enableCodecInterrupts(void)
  663. {
  664. }
  665.  
  666. static __inline__
  667. void disableCodecInterrupts(void)
  668. {
  669. }
  670.  
  671. static __inline__
  672. void stopDMA(void)
  673. {
  674.     writeToDSP(DC_HALT_DMA);
  675. }
  676.  
  677. /*
  678.  * This routine will stop input dma. 
  679.  */
  680. static __inline__
  681. void stopDMAInput(void)
  682. {
  683.     stopDMA();
  684. }
  685.  
  686. /*
  687.  * Likewise, but for output dma. 
  688.  */
  689. static __inline__
  690. void stopDMAOutput(void)
  691. {
  692.     stopDMA();
  693. }
  694.  
  695. /*
  696.  * Select between DSP_MONO_MODE and DSP_STEREO_MODE mode. Note that stereo
  697.  * recording is undocumented so it could potentially break on some clone
  698.  * cards. 
  699.  */
  700. static __inline__
  701. void setCodecDataMode(unsigned int mode, unsigned int dir)
  702. {
  703.     if (sbCardType.mixerPresent == NO)
  704.         return;
  705.         
  706.     if (dir == DMA_DIRECTION_OUT) {
  707.     if (mode == DSP_STEREO_MODE) {
  708.         sbPlayback.reg.stereo = SB_PLAYBACK_STEREO;
  709.     } else {
  710.         sbPlayback.reg.stereo = SB_PLAYBACK_MONO;
  711.     }
  712.     outbIXMixer(MC_PLAYBACK_CONTROL, sbPlayback.data);
  713.     } else if (dir == DMA_DIRECTION_IN)    {
  714.     dspWriteWait();
  715.     if (mode == DSP_STEREO_MODE) {
  716.         writeToDSP(DC_RECORD_IN_STEREO);
  717.     } else {
  718.         writeToDSP(DC_RECORD_IN_MONO);
  719.     }
  720.     }
  721. }
  722.  
  723.  
  724. static __inline__
  725. void setCodecSamplingRate(unsigned int rate)
  726. {
  727.     unsigned int timeConstant;
  728.     
  729.     /* Sanity check. */
  730.     if (rate < SB_MIN_SAMPLE_RATE)
  731.         rate = SB_MIN_SAMPLE_RATE;
  732.     else if (rate > SB_MAX_SAMPLE_RATE)
  733.         rate = SB_MAX_SAMPLE_RATE;
  734.         
  735.     dspWriteWait();
  736.     if (lowSpeedDMA)    {
  737.         timeConstant = 256 - (1000*1000)/rate;
  738.         writeToDSP(DC_SET_TIME_CONSTANT);
  739.     dspWriteWait();
  740.         writeToDSP(timeConstant);
  741. #ifdef DEBUG
  742.     IOLog("SoundBlaster8: Sample rate = %u, timeConstant = %x\n", rate, timeConstant);
  743. #endif DEBUG
  744.     } else {
  745.         timeConstant = 65536 - (256*1000*1000)/rate;
  746.         writeToDSP(DC_SET_TIME_CONSTANT);
  747.     dspWriteWait();
  748.         writeToDSP(timeConstant >> 8);
  749. #ifdef DEBUG
  750.     IOLog("SoundBlaster8: Sample rate = %u, timeConstant = %x\n", rate, timeConstant >> 8);
  751. #endif DEBUG
  752.     }
  753. }
  754.  
  755. /*
  756.  * We test here if the user supplied dma/irq selections are correct. Actually
  757.  * it is more complicated than this because not all kinds of cards can use
  758.  * all dma/irq combinations. We simply allow the superset and avoid
  759.  * complicated version dependent verification. (Available interrupts are 3,
  760.  * 5, 7 for SBPro and 5, 7, 10 for other kinds, clone cards may have slight
  761.  * differences.) 
  762.  */
  763.  
  764. static  __inline__
  765. BOOL
  766. checkSelectedDMAAndIRQ(unsigned int channel, unsigned int irq)
  767. {
  768.     BOOL status = YES;
  769.  
  770.     if ((channel != 0) && (channel != 1) && (channel != 3)) {
  771.         IOLog("SoundBlaster8: Audio DMA channel is %d.\n", channel);
  772.         IOLog("SoundBlaster8: Audio DMA channel must be one of 0, 1, 3.\n");
  773.         status = NO;
  774.     }
  775.     if ((irq != 3) && (irq != 5) &&
  776.         (irq != 7) && (irq != 10)) {
  777.         IOLog("SoundBlaster8: Audio irq is %d.\n", irq);
  778.         IOLog("SoundBlaster8: Audio IRQ must be one of 3, 5, 7, 10.\n");
  779.         status = NO;
  780.     }
  781.     
  782.     return status;
  783. }
  784.  
  785.